Skip to main content

Uniswap Core Concepts

Uniswap v4 is an automated market maker (AMM) facilitating efficient value exchange on the Ethereum Virtual Machine (EVM). Although Uniswap v4 introduces significant innovations, such as Hooks, the underlying mathematics remains rooted in V3 and will not change. Before we delve into the core of V4, let's take a moment to revisit the fundamental concepts behind Uniswap, particularly its mathematical framework.

Uniswap’s foundational mechanism is based on a simple yet powerful principle known as the constant product formula, or x * y = k. This formula governs how liquidity is provided, and trades are executed in Uniswap pools. In this model, x and y represent the reserves of two assets in a liquidity pool, and k is a constant that remains unchanged after every trade. The formula ensures that the product of the reserves stays balanced, providing an automated and efficient way to facilitate trades between two tokens.

The constant product formula is the heart of Uniswap’s decentralized trading model. By relying on this equation, Uniswap eliminates the need for traditional order books and centralized matching systems. Instead, liquidity providers (LPs) supply assets to the pool, and traders can instantly swap between assets based on the relative reserves and the price set by the formula. This unique approach allows Uniswap to offer a permissionless, non-custodial, and efficient way of trading on the blockchain.

However, Uniswap v3 introduced concentrated liquidity, where liquidity providers can choose to provide liquidity within a specific price range, improving capital efficiency. This innovation allowed LPs to concentrate their liquidity where it is most needed, reducing slippage and improving the pricing of assets in the pool. Despite these innovations, the underlying mathematical model based on the constant product formula remains unchanged in Uniswap v4, which means that liquidity is still managed within the constraints of this equation but with enhanced flexibility and new tools for customization.

To illustrate Uniswap's math calculations, consider an example involving two individuals: Alice, who acts as a liquidity provider, and Bob, who is a swap user.

Provide Liquidity

Imagine Alice wants to add liquidity to the pool by selecting two tokens: ETH (referred to as x) and USDC (referred to as y). Currently, the USDC/ETH exchange rate stands at 1000/1. Alice wishes to contribute liquidity to the pool; however, she does not intend to supply liquidity for the entire curve. Therefore, she has selected a specific range for providing liquidity. we use PminP_{min} and PmaxP_{max} to express range, and once out of range, she quit providing liquidity.

Let us consider the coordinate axes, where the x-axis represents ETH and the y-axis represents USDC. The curve defined within this coordinate system is expressed by the equation x * y = k. We should notice that the axis represents token amounts, not prices. We use P=yxP=\frac{y}{x} to express this ratio But for calculation convenience, we often use this form: P=yx\sqrt{P} = \sqrt{\frac{y}{x}}

When the price (or yx\frac{y}{x} ratio) moves to the left, reaching PminP_{min}, it indicates that the market now favors ETH. At this point, all of Alice's ETH will have been swapped for USDC. Consequently, she only holds USDC and has exited her liquidity position. Conversely, if the price (or yx\frac{y}{x} ratio) moves to the right, reaching PmaxP_{max}, the market favors USDC. In this case, all of Alice's USDC will have been swapped for ETH. At this point, she holds only ETH and similarly exits her liquidity position.

Instead of directly using price to define liquidity ranges, Uniswap uses ticks. A tick is the unit in Uniswap that defines price ranges, and this method enhances computational efficiency and simplifies range management.

In Uniswap, a tick corresponds to a logarithmic scale of price. Specifically, the relationship between tick(we use i to express tick) and price is given by the following formula:

P=1.0001ii=log1.0001P(i)\begin{aligned} P &= 1.0001^{i} \\ i &= log_{\sqrt{1.0001}}\sqrt{P(i)} \end{aligned}

This formula shows that the price PP is calculated as an exponential function of tick. Therefore, as the tick increases, the price increases, and conversely, as the tick decreases, the price decreases. Each tick corresponds to a specific price point, and liquidity providers can select the appropriate ticks to define the price range in which they wish to provide liquidity.

We use exponential form to express P in finance because it allows us to understand price changes in percentage terms rather than absolute values. This approach is essential for accurately representing financial fluctuations.

We also need to introduce a concept: the amount of liquidity LL. Liquidity in a pool is the combination of token reserves (that is, two numbers).

L=xyL = \sqrt{xy}

Once Alice provides liquidity, the value of LL remains constant, regardless of how the token reserves xx and yy fluctuate due to trading.

Now the USDC/ETH exchange rate is 1000/1. Suppose Alice wants to provide Δx\Delta x tokens for xx and Δy\Delta y tokens for yy . Then how many tokens should Alice provide?

Alice first choose Δx\Delta x and Δy\Delta y to calculate LL . She can reference the current exchange rate to provide Δx\Delta x and Δy\Delta y such as Δx\Delta x is 1 and Δy\Delta y being 1000. The formula to calculate LL is:

L=ΔxPmaxPcurrentPmaxPcurrentL=ΔyPcurrentPmin\begin{aligned} L &= \Delta x \frac{\sqrt{P_{max}}\sqrt{P_{current}}}{\sqrt{P_{max}} - \sqrt{P_{current}}} \\ L &= \frac{\Delta y}{\sqrt{P_{current}} - \sqrt{P_{min}}} \end{aligned}

We select the minimum value of LL because selecting a higher value of LL would require providing more tokens to maintain the same liquidity level. This may exceed Alice’s intended contribution.

At this stage, we select the smaller L and use it to compute the amount of the other token. The token corresponding to the smaller L does not need to be recalculated, as its amount is already determined by the chosen L.

Δx=(1Pcurrent1Pmax)LΔy=(PcurrentPmin)L\begin{aligned} \Delta x &= \left( \frac{1}{\sqrt{P_{current}}} - \frac{1}{\sqrt{P_{max}}} \right) L \\ \Delta y &= \left( \sqrt{P_{current}} - \sqrt{P_{min}} \right) L \end{aligned}

Now Alice successfully provides tokens to the pool, and the price won't change. The price only adjusts by swapping.

If Alice chooses a price range that does not contain the current price, there are two distinct scenarios to consider:

  1. If Alice sets a price range entirely below the current price ( PcurrentP_{current} ), she will only need to provide token0 (e.g., ETH). This is because, at prices above her selected range, all liquidity in that range would have already been converted to token0. In this case, the amount of token0 required is calculated by:

    Δx=(1Pmin1Pmax)L\Delta x = \left( \frac{1}{\sqrt{P_{min}}} - \frac{1}{\sqrt{P_{max}}} \right) L
  2. If Alice selects a price range entirely above the current price ( PcurrentP_{current} ), she will only need to provide token1 (e.g., USDC). This occurs because, at prices below her selected range, all liquidity would have been converted into token1. The amount of token1 required is calculated by:

    Δy=(PmaxPmin)L\Delta y = \left( \sqrt{P_{max}} - \sqrt{P_{min}} \right) L

In both scenarios, L represents the liquidity amount, and P_min and P_max define the price range boundaries. This flexibility in range selection allows liquidity providers to position their assets according to their market expectations.

Swap

After Alice provided liquidity to the pool, Bob now wants to sell some tokens y ( Δy\Delta y ) from the pool to buy tokens x ( Δx\Delta x).

Scenario 1: Don't need to cross-tick swap

Let's start with a simple scenario: Bob swaps within Alice's price range, and Alice's liquidity is sufficient to fulfill Bob's trade without pushing the price out of her range. It's important to note that the liquidity L at any tick is the total sum of all contributions. If Tom also provides liquidity within the same price range, his L is added to Alice's, forming the total liquidity available for swaps at that tick. In the next calculation, we use sum L and L = Alice L + Tom L. L is a constant number when providing liquidity, adding to the contrast. So we can easily calculate the sum L before Bob swaps.

We can use this equation to calculate Δx\Delta x that Bob can receives.

Δx=Δ1PLΔ1P=1Ptarget1Pcurrent\begin{aligned} \Delta x &= \Delta \frac{1}{\sqrt{P}}L \\ \Delta \frac{1}{\sqrt{P}} &= \frac{1}{\sqrt{P_{target}}} - \frac{1}{\sqrt{P_{current}}} \end{aligned}

How do we know Ptarget\sqrt{P_{target}} ?

We can use this formula to calculate it.

ΔP=ΔyLPtarget=Pcurrent+ΔP\begin{aligned} \Delta \sqrt{P} &= \frac{\Delta y}{L} \\ \sqrt{P_{target}} &= \sqrt{P_{current}} + \Delta \sqrt P \end{aligned}

Now the price PcurrentP_{current} moves to PtargetP_{target} as Bob sells his tokens Δy\Delta y and receives tokens Δx\Delta x .

Scenario 2: Cross-tick swap